﻿using System;

namespace Geometria.Angulos
{
    public struct AnguloCompuesto
    {
        #region Fields

        public static Radian MaxZ = Math.PI / 2;
        public static Radian MinZ = Math.PI / 2;

        private Radian xy;
        private Radian _z;

        #endregion Fields

        #region Constructors

        public AnguloCompuesto(Radian xy, Radian _z)
        {
            this.xy = xy;
            this._z = _z;
        }

        public AnguloCompuesto(double x, double y, double z)
        {
            this.xy = Math.Atan2(x, y);
            this._z = Math.Atan2(Hipotenusa(x, y), z);
        }

        #endregion Constructors

        #region Properties

        /// <summary>
        /// Angulo medido en el plano XY
        /// </summary>
        public Radian XY
        {
            get
            {
                return this.xy;
            }
            set
            {
                this.xy = value;
            }
        }

        /// <summary>
        /// Angulo medido entre el eje Z y el angulo en XY
        /// </summary>
        public Radian Z
        {
            get
            {
                return this._z;
            }
            set
            {
                Radian temp = Radian.Normalize(value);

                if (temp > Radian.MaxValue || temp < Radian.MinValue)
                {
                    this.xy = Radian.Normalize(this.xy + Radian.MaxValue);

                    if (temp > Radian.MaxValue)
                    {
                        this._z = 2 * Radian.MaxValue - temp;
                    }
                    else //if (temp < Radian.MinValue)
                    {
                        this._z = 2 * Radian.MinValue - temp;
                    }
                }

                this._z = value;
            }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Genera un vector de módulo unitario
        /// </summary>
        /// <returns></returns>
        public Vector GenerarVector()
        {
            double x, y, z;

            x = Math.Cos(this.XY) * Math.Cos(this.Z);
            y = Math.Sin(this.XY) * Math.Cos(this.Z);
            z = Math.Sin(this.Z);

            return new Vector(x, y, z);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="magnitud"></param>
        /// <returns></returns>
        public Vector GenerarVector(double magnitud)
        {
            return this.GenerarVector() * magnitud;
        }

        private static double Hipotenusa(double cateto1, double cateto2)
        {
            return Math.Sqrt(cateto1 * cateto1 + cateto2 * cateto2);
        }

        #endregion Methods
    }
}